package com.moyuxi.sound_of_the_forest

import android.media.AudioAttributes
import android.media.MediaPlayer
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.moyuxi.sound_of_the_forest.entity.LocalMusicBean
import java.io.IOError
import java.io.IOException

class MediaPlayerHelper private constructor() {

    companion object {
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            MediaPlayerHelper()
        }
    }

    private val TAG: String = "MediaPlayerHelper"

    /**
     * 媒体播放器对象
     */
    private val mediaPlayer = MediaPlayer()

    /**
     * 正在播放的音乐的位置
     */
    private var playIndex = -1

    /**
     * 暂停音乐时进度条的位置
     */
    private var pauseCP = 0

    /**
     * 首次启动
     */
    private var isFirstRun = false


    private val _playMusicList = MutableLiveData<List<LocalMusicBean>>()

    /**
     * 播放列表
     */
    val playMusicList: LiveData<List<LocalMusicBean>> = _playMusicList


    private val _playMusicBean =
        MutableLiveData(LocalMusicBean(name = "选择一首歌来听听吧", singer = "by 林鸣"))

    /**
     * 正在播放的歌曲
     */
    val playMusicBean: LiveData<LocalMusicBean>
        get() = _playMusicBean


    private val _isPlaying = MutableLiveData(false)

    /**
     * 播放状态
     */
    val isPlaying: LiveData<Boolean> = _isPlaying


    private val _playingProgress = MutableLiveData(0.0f)

    /**
     * 播放进度
     */
    val playingProgress: LiveData<Float> = _playingProgress


    /**
     * 设置播放列表数据
     */
    fun setPlayMusicList(value: List<LocalMusicBean>) {
        if (value.isEmpty()) return
        _playMusicList.value = value
        _playMusicBean.value?.let { item ->
            playIndex = findIndexByList(item).let { if (it == -1) 0 else it }
        }
    }

    /**
     * 添加至播放列表
     */
    fun addSongToPlaylist(value: LocalMusicBean) {
        // 追加
        _playMusicList.value = _playMusicList.value?.let { it + value } ?: run { // 初始化播放器并添加
            playIndex = 0
            mediaPlayer.apply {
                // 重置播放器
                reset()
                try {
                    setDataSource(value.path)
                    prepare()
                    onMusicChanged(value)
                } catch (e: IllegalStateException) {
                    Log.e(TAG, "playMusicInBean: aaa $e ${e.message} ${e.localizedMessage}")
                } catch (e: IOError) {
                    Log.e(TAG, "playMusicInBean: ${e.message}")
                }
            }
            listOf(value)
        }
    }

    /**
     * 从播放列表中移出
     */
    fun removeBeanOnList(bean: LocalMusicBean) {
        if (_playMusicList.value == null) return
        findIndexByList(bean).let {
            if (it != -1) {
                if (_playMusicList.value!!.size <= 1) {
                    stopMusic()
                    onMusicChanged(LocalMusicBean(name = "选择一首歌来听听吧", singer = "by 林鸣"))
                    _playMusicList.value = arrayListOf()
                    _playingProgress.postValue(0f)
                } else {
                    _playMusicBean.value?.let { it1 ->
                        findIndexByList(it1).let { it2 ->
                            if (it < it2) playIndex -= 1
                            else if (it == it2) playNextMusic()
                        }
                    }
                    _playMusicList.value =
                        _playMusicList.value?.minus(bean)?.toSet()?.toList() ?: arrayListOf()
                }
            }
        }
    }

    /**
     * 播放上一首
     */
    fun playLastMusic() {
        if (!_playMusicList.isInitialized || _playMusicList.value?.isEmpty() == true) return
        _playMusicList.value?.let {
            if (playIndex <= 0) playIndex = it.size - 1 else playIndex -= 1
            playMusicInBean(it[playIndex])
        }

    }

    /**
     * 播放下一首
     */
    fun playNextMusic() {
        if (!_playMusicList.isInitialized || _playMusicList.value?.isEmpty() == true) return
        _playMusicList.value?.let {
            if (playIndex >= it.size - 1) playIndex = 0 else playIndex += 1
            playMusicInBean(it[playIndex])
        }
    }

    /**
     * 播放指定的音乐
     */
    fun playMusicInBean(bean: LocalMusicBean) {
        // 首次mediaPlayer处理，以及往后初始化部分数据。
        stopMusic()
        mediaPlayer.apply {
            // 重置播放器
            reset()
            try {
                setDataSource(bean.path)
                prepare()
                playIndex = findIndexByList(bean).let {
                    if (it == -1) {
                        _playMusicList.value = _playMusicList.value?.plus(bean) ?: arrayListOf(bean)
                        findIndexByList(bean)
                    } else it
                }
                onMusicChanged(bean)
                playMusic()
            } catch (e: IllegalStateException) {
                Log.e(TAG, "playMusicInBean: prepare() 异常 $e")
            } catch (e: IOError) {
                Log.e(TAG, "playMusicInBean: ${e.message}")
            }
        }
    }

    /**
     * 停止播放
     */
    fun stopMusic() {
        if (isFirstRun) {
            if (mediaPlayer.isPlaying) mediaPlayer.stop()
            pauseCP = 0
            _playingProgress.value = 0f
            _isPlaying.value = false
        } else {
            isFirstRun = true
            mediaPlayer.run {
                setAudioAttributes(
                    AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                        .setUsage(AudioAttributes.USAGE_MEDIA).build()
                )
                setOnCompletionListener {
                    _isPlaying.value = false
                    mediaPlayer.seekTo(0)
                    if (_playMusicList.value != null && _playMusicList.value!!.isNotEmpty()) playNextMusic()
                    else stopMusic()
                }
            }
        }
    }

    /**
     * 线程更新播放进度值
     */
    private val jobRunnable = Runnable {
        var fl = 0f
        while (_isPlaying.value == true) {
            fl =
                (mediaPlayer.currentPosition.toFloat() / mediaPlayer.duration.toFloat()).let { if (it.isNaN()) 0f else it }
            _playingProgress.postValue(fl)
            Thread.sleep(640)
        }
    }

    private var job = Thread(jobRunnable)

    /**
     * 暂停/播放状态切换
     */
    fun playCurrentMusic() {
        if (!_playMusicList.isInitialized || _playMusicList.value?.isEmpty() == true) return
        if (playIndex == -1) {
            playIndex = 0
            _playMusicList.value?.get(playIndex)?.let { playMusicInBean(it) }
        } else {
            if (mediaPlayer.isPlaying) pauseMusic()
            else playMusic()
        }
    }

    /**
     * 播放状态-播放
     */
    private fun playMusic() {
        mediaPlayer.run {
            if (!_isPlaying.value!!) try {
                if (pauseCP != 0) seekTo(pauseCP)
                start()
                _isPlaying.value = true
                job.name = "onProgressListener"
                // 防止启动多次及销毁后启动新线程
                if (!job.isAlive) {
                    job = Thread(jobRunnable)
                    job.start()
                }
            } catch (e: IllegalStateException) {
//                    Toast.makeText(context, "播放器播放错误", Toast.LENGTH_LONG).show()
                Log.e(TAG, "playMusic: $e -> ${e.printStackTrace()}")
            } catch (e: IOException) {
//                    Toast.makeText(context, "播放器播放错误", Toast.LENGTH_LONG).show()
                Log.e(TAG, "playMusic: $e -> ${e.message}")
            }
        }
    }

    /**
     * 播放状态-暂停
     */
    private fun pauseMusic() {
        pauseCP = mediaPlayer.run {
            if (isPlaying) {
                pause()
                _isPlaying.value = false
                currentPosition
            } else 0
        }

    }

    /**
     * 切换当前播放的音乐信息
     */
    private fun onMusicChanged(bean: LocalMusicBean) {
        _playMusicBean.value = bean
    }

    /**
     * 查找歌曲在列表中的位置
     */
    private fun findIndexByList(bean: LocalMusicBean): Int {
        if (_playMusicList.value?.isEmpty() == true) return -1
        return _playMusicList.value?.indexOf(bean) ?: -1
    }
}